#include "ET++.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "WindowColorMap.h"
#include "Class.h"
#include "String.h"
#include "ET_stdio.h"

//---- WindowColorMap ----------------------------------------------------------

NewMetaImpl(WindowColorMap,RefCounted, (T(id), TB(rw), T(changed)));

int WindowColorMap::cnt= 1000;

WindowColorMap::WindowColorMap(bool readwrite)
{
	id= WindowColorMap::cnt++;
	changed= 0;
	rw= readwrite;
	grey= FALSE;
}

WindowColorMap::WindowColorMap(WindowColorMap *from)
{
	id= WindowColorMap::cnt++;
	changed= 0;
	rw= from->rw;
	grey= from->grey;
}

WindowColorMap::~WindowColorMap()
{
}

WindowColorMap *WindowColorMap::DevMakeCopy(WindowColorMap*)
{
	return this;
}

u_long WindowColorMap::AllocateAndSetCell(long id, RGB *rgb, WindowPort *port)
{
	if (rw)
		return DevAllocateAndSetCell(id, rgb, port);
	return RGB2Index(rgb);
}

void WindowColorMap::DevInstall(Port*)
{
	changed= 0;
}

u_long WindowColorMap::DevRGB2Index(RGB *c, RGB*)
{
	return DevRGB2Index2(c);
}

u_long WindowColorMap::DevRGB2Index2(RGB*)
{
	return 0;
}

void WindowColorMap::DevIndex2RGB(u_long, RGB*)
{
}

u_long WindowColorMap::DevAllocateAndSetCell(long, RGB*, WindowPort*)
{
	return 0;
}

//---- WindowIndexMapper -------------------------------------------------------

NewMetaImpl(WindowIndexMapper,WindowColorMap, (T(length)));

WindowIndexMapper::WindowIndexMapper(bool readwrite) : WindowColorMap(readwrite)
{
	length= 0;
	realmap= new RGB[256];
	graymap= new u_long[256];
	rgbmap= new u_long[256];
}

WindowIndexMapper::WindowIndexMapper(WindowIndexMapper *from)
							: WindowColorMap(from)
{
	length= from->length;
	realmap= new RGB[256];
	MemCpy(realmap, from->realmap, 256 * sizeof(RGB));
	graymap= new u_long[256];
	MemCpy(graymap, from->graymap, 256 * sizeof(u_long));
	rgbmap= new u_long[256];
	MemCpy(rgbmap, from->rgbmap, 256 * sizeof(u_long));
}

WindowIndexMapper::~WindowIndexMapper()
{
	SafeDelete(realmap);
	SafeDelete(graymap);
	SafeDelete(rgbmap);
}

u_long WindowIndexMapper::DevRGB2Index(RGB *c, RGB *result)
{
	u_long id, ix;

	if (grey || (c->red == c->green && c->green == c->blue)) {
		if (grey)
			id= c->AsGreyLevel();
		else
			id= c->red;
		ix= graymap[id];
		if (ix == 0) {
			RGB rc((short)((id / (MAXGREYS-1)) * (MAXGREYS-1)));
			graymap[id]= ix= DevRGB2Index2(&rc);
		}
		/*
		if (type[ix])
			ix= graymap[v]= FindGray(v);
		*/
	} else {
		id= Pixel(c->red, c->green, c->blue);
		ix= rgbmap[id];
		if (ix == 0) {
			RGB rc;
			rc.red= (c->red / (MAXREDS-1)) * (MAXREDS-1);
			rc.green= (c->green / (MAXGREENS-1)) * (MAXGREENS-1);
			rc.blue= (c->blue / (MAXBLUES-1)) * (MAXBLUES-1);
			rgbmap[id]= ix= DevRGB2Index2(&rc);
		}

		/*
		if (type[ix])
			ix= FindRGB(c);
		*/
	}
	// usecnt[ix]++;

	if (result)
		*result= realmap[ix];
	return ix;
}

void WindowIndexMapper::DevIndex2RGB(u_long ix, RGB *result)
{
	*result= realmap[ix];
}

//---- ColorDirectMapper -------------------------------------------------------

NewMetaImpl(ColorDirectMapper,WindowColorMap, (T(rmask), T(gmask), T(bmask),
						T(rshift), T(gshift), T(bshift)));

int findshift(u_long m)
{
	register int i;
	for (i= 0; i < 32; i++)
		if (m & (1 << i))
			return i;
	return 0;
}

ColorDirectMapper::ColorDirectMapper(u_long rm, u_long gm, u_long bm,
					bool readwrite) : WindowColorMap(readwrite)
{
	rmask= rm;
	gmask= gm;
	bmask= bm;
	rshift= findshift(rmask);
	gshift= findshift(gmask);
	bshift= findshift(bmask);
	rmul= 8-3;
	gmul= 8-3;
	bmul= 8-2;

	fprintf(stderr, "%08x %d %d %08x %d %d %08x %d %d\n",
		rmask, rshift, rmul, gmask, gshift, gmul, bmask, bshift, bmul);
}

u_long ColorDirectMapper::DevRGB2Index(RGB *c, RGB *result)
{
#if 1
	u_long ix=  ((c->blue  << bshift) & bmask) +
				((c->green << gshift) & gmask) +
				((c->red   << rshift) & rmask);
#else
	u_long ix=  (((c->blue >> bmul) << bshift) & bmask) +
				(((c->green>> gmul) << gshift) & gmask) +
				(((c->red  >> rmul) << rshift) & rmask);
#endif
	if (result)
		*result= *c;
	return ix;
}

void ColorDirectMapper::DevIndex2RGB(u_long ix, RGB *result)
{
#if 1
	result->blue=   (short) ((ix & bmask) >> bshift);
	result->green=  (short) ((ix & gmask) >> gshift);
	result->red=    (short) ((ix & rmask) >> rshift);
#else
	result->blue=   (short) ((ix & bmask) >> bshift) << bmul;
	result->green=  (short) ((ix & gmask) >> gshift) << gmul;
	result->red=    (short) ((ix & rmask) >> rshift) << rmul;
#endif
}

